package com.bangyo.core.manager;

import java.sql.Timestamp;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sothis.util.DateUtils;

import com.bangyo.core.action.OperatorActionLogFactory;
import com.bangyo.core.entity.AbstractEntity;
import com.bangyo.core.persister.EntityPersister;

public abstract class AbstractEntityManager<E extends AbstractEntity> implements
    EntityManager<E>
{
    private EntityPersister<E> entityPersister = null;

    private Log logger = LogFactory.getLog(getClass());

    public E create(UserContext context, E entity)
    {
        if (!context.hasLogin())
        {
            if (logger.isWarnEnabled())
            {
                logger.warn("User has not logined.");
            }
            return null;
        }

        if (!judgeUniqueness(context, entity))
        {
            if (logger.isWarnEnabled())
            {
                logger
                    .warn(entity.getClass().getName()+" has existed."
                        +entity.getClass().getName()+".poin=["+entity.getPoin()
                        +"]");
            }
            return null;
        }

        Timestamp now = DateUtils.now();

        OperatorActionLogFactory.copy(entity.getCreatorActionLog(), context);
        entity.getCreatorActionLog().setOperatedDateTime(now);
        OperatorActionLogFactory.copy(entity.getLastModifierActionLog(),
            context);
        entity.getLastModifierActionLog().setOperatedDateTime(now);

        if (0==entityPersister.create(entity))
        {
            if (logger.isWarnEnabled())
            {
                logger.warn("Create "+entity.getClass().getName()+" failed.");
            }
            return null;
        }

        return entity;
    }

    public E modify(UserContext context, E entity)
    {
        if (context.getUserPoin()!=entity.getCreatorActionLog()
            .getOperatorUserPoin())
        {
            if (logger.isWarnEnabled())
            {
                logger
                    .warn("User can not modify "+entity.getClass().getName()
                        +".userPoin=["+context.getUserPoin()+"],"
                        +entity.getClass().getName()+".poin=["+entity.getPoin()
                        +"]");
            }
            return null;
        }

        if (null==entityPersister.getByKey(entity.getPoin()))
        {
            if (logger.isWarnEnabled())
            {
                logger.warn(entity.getClass().getName()+" is not existent."
                    +entity.getClass().getName()+".poin=["+entity.getPoin()
                    +"].");
            }
            return null;
        }

        Timestamp now = DateUtils.now();

        OperatorActionLogFactory.copy(entity.getLastModifierActionLog(),
            context);
        entity.getLastModifierActionLog().setOperatedDateTime(now);

        if (null==entityPersister.update(entity))
        {
            if (logger.isWarnEnabled())
            {
                logger
                    .warn("Modify "+entity.getClass().getName()+" failed."
                        +entity.getClass().getName()+".poin=["+entity.getPoin()
                        +"]");
            }
            return null;
        }

        return entity;
    }

    public boolean delete(UserContext context, long entityPoin, boolean physics)
    {
        E entity = entityPersister.getByKey(entityPoin);

        if (null==entity)
        {
            if (logger.isWarnEnabled())
            {
                logger.warn(entity.getClass().getName()+" is not existent."
                    +entity.getClass().getName()+".poin=["+entityPoin+"].");
            }
            return false;
        }

        if (context.getUserPoin()!=entity.getCreatorActionLog()
            .getOperatorUserPoin())
        {
            if (logger.isWarnEnabled())
            {
                logger.warn("User can not delete "+entity.getClass().getName()
                    +".userPoin=["+context.getUserPoin()+"],"
                    +entity.getClass().getName()+".poin=["+entityPoin+"]");
            }
            return false;
        }

        if (physics)
        {
            entityPersister.deleteByEntity(entity);
        }
        else
        {
            Timestamp now = DateUtils.now();

            entity.setDefunct(true);
            OperatorActionLogFactory.copy(entity.getLastModifierActionLog(),
                context);
            entity.getLastModifierActionLog().setOperatedDateTime(now);

            if (null==entityPersister.update(entity))
            {
                if (logger.isWarnEnabled())
                {
                    logger.warn("Delete "+entity.getClass().getName()
                        +" failed."+entity.getClass().getName()+".poin=["
                        +entity.getPoin()+"]");
                }
                return false;
            }
        }

        return true;
    }

    protected abstract boolean judgeUniqueness(UserContext context, E entity);

    public void setEntityPersister(EntityPersister<E> entityPersister)
    {
        this.entityPersister = entityPersister;
    }
}
